#encoding=utf-8
import copy

import re
from string import Template

import jsonpath
import yaml

from common.read_write_yaml import write_yaml, read_all_yaml
from hotload.debug_talk import *


class ExtractUtil:

    def extract(self, res_name, tiqu_name, attr_name, exp, index):
        # 深拷贝相应值
        new_res = copy.deepcopy(res_name)
        try:
            new_res.json = new_res.json()
        except Exception():
            new_res.json = {"msg": "response is not a json"}
        # 通过反射获取属性的值
        data = getattr(new_res, attr_name, "not find")
        # 判断是以什么方式提取
        if exp.startswith("$."):
            lis = jsonpath.jsonpath(dict(data), exp)
        else:
            lis = re.findall(exp, data)
        # 通过下标取值
        if lis:
            write_yaml({tiqu_name: lis[index]})

    def change(self, request_data: dict):
        # 1、把字典转化成字符串
        request_data_str = yaml.safe_dump(request_data)
        # 2、将请求数据中含有的${number}转化成对应的函数调用
        new_request_data = self.hotload_extract(request_data_str)
        # 3、将替换后的字符串转化为字典
        new_request_data_dict = yaml.safe_load(new_request_data)
        return new_request_data_dict

    # 使用了模版替换方法进行的替换
    # def use_extract(self, request_data: dict):
    #     # 把字典转化为字符串
    #     str_request_data = yaml.safe_dump(request_data)
    #     # 通过模板方法替换字符串中对应的值
    #     new_request_data = Template(str_request_data).safe_substitute(read_all_yaml())
    #     # 把字符串转化为字典
    #     return yaml.safe_load(new_request_data)

    # 使用热加载的方式对请求中的数据进行替换
    def hotload_extract(self, data_str: str):
        # print("调用了热加载的替换方法")
        # 定义一个正则匹配这种表达式
        regexp = "\\$\\{(.*?)\\((.*?)\\)\\}"
        # 通过正则表达式的方式对表达式的内容进行匹配，得到所有的表达式list
        fun_list = re.findall(regexp, data_str)
        # 遍历查找到的内容
        for fun in fun_list:
            # 首先判断是否包含有参数
            if fun[1] == "":
                new_value = getattr(DebugTalk(), fun[0])()
            else:
                new_value = getattr(DebugTalk(), fun[0])(*fun[1].split(","))
            # 如果value是一个数字格式的字符串
            if isinstance(new_value, str) and new_value.isdigit():
                new_value = "'" + new_value + "'"
            # 拼接旧值
            old_data = "${" + fun[0] + "(" + fun[1] + ")}"
            # 替换新值
            data_str = data_str.replace(old_data, new_value)
        # 返回替换后的字符串
        return data_str
